using Abc.Application.HtAdmin.Dto;
using Abc.Core;
using Abc.Core.Entities;

using Furion.DatabaseAccessor;
using Furion.DataEncryption.Extensions;
using Furion.DependencyInjection;

using Mapster;

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;

using Serilog;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

using Tool;

namespace Abc.Application
{
    [Injection(Proxy = typeof(LogDispatchProxy))]
    public class HtAdminService : IHtAdminService, ITransient
    {
        private readonly ILogger _logger;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IRepository<Menu> _menuRepository;
        private readonly IRepository<User> _userRepository;
        private readonly IAdminManager _adminManager;
        public HtAdminService(IRepository<Menu> menuRepository
            , IHttpContextAccessor httpContextAccessor
            , ILogger logger
            , IRepository<User> userRepository
            , IAdminManager adminManager)
        {
            _logger = logger;
            _menuRepository = menuRepository;
            _httpContextAccessor = httpContextAccessor;
            _userRepository = userRepository;
            _adminManager = adminManager;
        }

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<PearMenuItem>> GetMenus()
        {
            //var menus = new List<PearAdminMenuitemDto>();
            var dbmenus = await _menuRepository.DetachedEntities
.Where(o => o.IsEnable && o.IsShow)
.Select(o => new PearMenuInput() { MenuType = o.MenuType, MId = o.MId, PMId = o.PMId, Name = o.Name, Icon = o.Icon, Sort = o.Sort, Url = o.Url }).ToListAsync();
            var rmenus = dbmenus.GetMenus(pid: "");
            return rmenus;
        }

        /// <summary>
        /// 管理登陆
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultData<AdminOut>> Login(AdminLoginDto model)
        {
            var resultdata = new ResultData<AdminOut>();

            var pwd = model.PassWord.ToPBKDF2Encrypt();
            var dbmodel = await _userRepository.Include(o => o.Roles).ThenInclude(o => o.Permissions)
.FirstOrDefaultAsync(o => (o.UserType == UserType.系统维护 || o.UserType == UserType.超级管理员 || o.UserType == UserType.管理员) && o.Account == model.Account);
            if (dbmodel == null)
            {
                resultdata.Errors = "账号或密码错误";
                return resultdata;
            }

            if (!model.PassWord.ToPBKDF2Compare2(dbmodel.Pwd))
            {
                resultdata.Errors = "账号或密码错误";
                return resultdata;
            }

            dbmodel.LastLoginTime = DateTimeOffset.Now;

            // var httpContextAccessor = App.GetService<IHttpContextAccessor>();

            #region 日志

            //var ip = _httpContextAccessor?.HttpContext?.GetLocalIpAddressToIPv4();
            //var newlog = new WebLog()
            //{
            //    CreationTime = DateTimeOffset.Now,
            //    RemoteAddr = ip,
            //    RequestUrl = _httpContextAccessor?.HttpContext?.Request?.Path,
            //    Par1 = _httpContextAccessor?.HttpContext?.Request?.Headers["User-Agent"].ToString(),
            //    Type = "管理员登录",
            //    LogContent = $"登陆账号：{dbmodel.Account} 登陆账号ID：{dbmodel.Id} IP:{_httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString()}"

            //};

            //_userRepository.Change<WebLog>().Insert(newlog);

            #endregion 日志

            #region claims

            var identity = new
                ClaimsIdentity(AuthorizeType.AdminAuthenticationScheme);//一定要声明AuthenticationScheme
            identity.AddClaim(new Claim(ClaimTypes.Name, dbmodel.Nick.ToString()));
            identity.AddClaim(new Claim(ClaimTypes.Sid, dbmodel.Id.ToString()));
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, dbmodel.Account.ToString()));

            await _httpContextAccessor.HttpContext.SignInAsync(identity.AuthenticationType,
                new ClaimsPrincipal(identity),
                new AuthenticationProperties
                {
                    IsPersistent = true,
                    RedirectUri = "/HtAdmin/Home/Index",
                });

            #endregion claims

            resultdata.Data = dbmodel.Adapt<AdminOut>();
            resultdata.Succeeded = true;
            resultdata.Errors = "登陆成功";

            dbmodel.SetMemoryCache($"Admin_{dbmodel.Id}", new Microsoft.Extensions.Caching.Memory.MemoryCacheEntryOptions()
            {
                SlidingExpiration = TimeSpan.FromMinutes(30),//滑动过期时间
            });
            // _memoryCache.Set($"Admin_{dbmodel.Id}", dbmodel.Roles);

            return resultdata;
        }

        /// <summary>
        /// 获取当前登陆用户
        /// </summary>
        /// <returns></returns>
        public async Task<AdminOut> GetLoginUser()
        {
            var userid = _adminManager.UserId;

            var user = await _userRepository.FirstOrDefaultAsync(o => o.Id == userid);
            return user.Adapt<AdminOut>();
        }

    }

    public interface IHtAdminService
    {
        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <returns></returns>
        Task<List<PearMenuItem>> GetMenus();

        /// <summary>
        /// 管理登陆
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<ResultData<AdminOut>> Login(AdminLoginDto model);

        /// <summary>
        /// 获取当前登陆用户
        /// </summary>
        /// <returns></returns>
        Task<AdminOut> GetLoginUser();

        ///// <summary>
        ///// 新增或更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> InsertOrUpdate(UserInput input);
        ///// <summary>
        ///// 查询一条[跟踪实体]
        ///// </summary>
        ///// <param name="id"></param>
        //Task<UserOut> Get(int id);
        ///// <summary>
        ///// 删除一条
        ///// </summary>
        ///// <param name="id"></param>
        //Task<ResultData<string>> Delete(int id);
        ///// <summary>
        ///// 分页查询
        ///// </summary>
        ///// <param name="searchQuery"></param>
        ///// <returns></returns>
        //Task<PagedListToLayui<UserOut>> GetAllByPageToLayui(UserQuery searchQuery);
        ///// <summary>
        ///// 设置状态
        ///// </summary>
        ///// <param name="id"></param>
        ///// <param name="state"></param>
        ///// <param name="field">字段名</param>
        ///// <returns></returns>
        //Task<ResultData<string>> SetState(int id, bool state, string field);
    }
}